/*

  Ronin Consulting, Inc.
    Copyright (C) 1992, Nicholas Christopher (nwc@gun.com)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
#import <pwd.h>
#import <libc.h>
#import "version.h"
#import "Defaults.h"
#import "EnhancedText.h"
#import "EnhancedApp.h"
#import "Subprocess.h"
#import "ConController.h"
#import "LogController.h"
#import "InfoController.h"
#import "SweepView.h"
#import <appkit/ScrollView.h>
#import <appkit/PopUpList.h>
#import <appkit/Window.h>
#import <appkit/Matrix.h>
#import <string.h>

static char tempFile[30] =  "/tmp/.UUCon.XXXXXX"; 
static void sweepIncrement(DPSTimedEntry teNumber, double now, void *userData);

@interface ConController (PRIVATE)	     /* Private methods */
-_startSweep;
-_endSweep;
@end

@implementation ConController

- init
{
   [super init];

   [NXApp appDirectory];		     /* cd to Apps directory so files in wrapper can be found */
   defaults = [Defaults new];		 
   teNum = (DPSTimedEntry)0;
   procType = NO_SPROC;
   logfile = syslog = nil;
   return self;
}


- pollHost:sender
{

   const char *host = [hostsPopUp title];
   char buff[80 + strlen(host)];

   if(procType != NO_SPROC)
       return self;

   sprintf(buff,"Polling host: %s\n", host);
   [consoleLog appendString: buff];

   [self _startSweep];

   if(*[defaults get: "DebugPoll"] == 'Y' && !auditProc)
   {
      auditFile = mktemp(tempFile);	     /* build a temporary audit file */
      sprintf(buff,"/usr/lib/uucp/uucico -r1 -s%s -x9 2> %s", host, auditFile);
   }
   else
   {
      [consoleLog appendString: "\nStarting to Poll - check log tool to watch progress\n"];
      sprintf(buff,"uupoll %s", host);
   }

   procType = POLL_HOST;
   subProc = [[Subprocess alloc] init: buff withDelegate: self];

   if(*[defaults get: "DebugPoll"] == 'Y')
   {
      sprintf(buff, "tail -f %s", auditFile);
      auditProc = [[Subprocess alloc] init: buff withDelegate: self];
   }

   return self;
}

- getBPS: sender
{
   char cmd[512] = "tail -14 /usr/spool/uucp/SYSLOG | fgrep bytes | \
         awk '/failed/ { printf \" %8d bytes %8s (%8s) in %7.2f sec FAILED\\n\",\
         $7, $5, $2, $9 } \
         { if ( $7 > 100 && ($9 + 0) > 0) \
            { bytes += $7; seconds += $9; \
            printf \"%8d bytes %8s(%s) in %7.2f\\n\", $7, $5, $2, $9}} \
         END { printf \"\\nAvg %8.2f bps\\n\", (bytes/seconds) * 8 }'"; 

   if (procType != NO_SPROC)
       return self;

   [self _startSweep];
   [consoleLog appendString: "Speed of last 7 jobs\n"];
   procType = GET_BPS;
   subProc = [[Subprocess alloc] init: cmd withDelegate: self];

   return self;
                                          
}

- hostsQueue:sender
{
   const char *host = [hostsPopUp title];
   char buff[80 + strlen(host)];
   
   if(procType != NO_SPROC)
       return self;

   [self _startSweep];

   sprintf(buff,"Queue for host: %s\n", host);
   [consoleLog appendString: buff];
   
   sprintf(buff,"uuq -l -s%s -b%s", host, [defaults get: "BaudRate"]);

   procType = HOST_QUEUE;
   subProc = [[Subprocess alloc] init: buff withDelegate: self];

   return self;
}

- hostsSnap:sender
{
   if(procType != NO_SPROC)
       return self;

   [self _startSweep];

   [consoleLog appendString: "Snapshot of uucp hosts\n"];
   
   procType = SNAP_HOSTS;
   subProc = [[Subprocess alloc] init: "uusnap" withDelegate: self];

   return self;
}

- setConsoleLog:sender
{
   consoleLog = [sender docView];
   return self;
}

- deleteJob:sender
{
   const char *host = [hostsPopUp title];
   const char *job = [consoleLog selectedText];
   char buff[80 + strlen(host) + strlen(job)];

   if(procType != NO_SPROC)
       return self;

   [self _startSweep];

   sprintf(buff,"Deleting job %s for host: %s\n", job, host);
   [consoleLog appendString: buff];
   sprintf(buff, "uuq -s%s -d%s", host, job);
   
   procType = DELETE_JOB;
   subProc = [[Subprocess alloc] init: buff withDelegate: self];

   return self;
}

- keyWindowLogClear: sender
{
   id keyController = [[NXApp keyWindow] delegate];


   if([keyController respondsTo: @selector(logClear)])
       [keyController logClear];

   return self;
}

- logClear
{
   [consoleLog empty: self];
   return self;
}

- syslog: sender
{
   if(!syslog)
       syslog = [[LogController alloc] initForCommand: "tail -10f /usr/spool/uucp/SYSLOG" entitled: "SYSLOG" ];

   [syslog makeKeyAndOrderFront: self];

   return self;
}


- logfile: sender
{

   if(!logfile)
       logfile = [[LogController alloc] initForCommand: "tail -10f /usr/spool/uucp/LOGFILE" entitled: "LOGFILE" ];

   [logfile makeKeyAndOrderFront: self];

   return self;
}

@end					     /* ConController */

@implementation ConController (PRIVATE)

-_startSweep
{
   [progress setIntValue: 0];
   teNum = DPSAddTimedEntry(.02, sweepIncrement, &progress, NX_RUNMODALTHRESHOLD + 1);
   return self;
}

-_endSweep
{
   if(teNum)
   {
      DPSRemoveTimedEntry(teNum);
      teNum = (DPSTimedEntry)0;
   }

   [progress setIntValue: -1];
//   [progress display];			     
   return self;
}

@end					     /* ConController (PRIVATE) */

@implementation ConController (ApplicationDelegate)

- appDidInit:sender
{
   /* if this program is set gid to daemon and L.sys is group readable to same we can debug */
   setgid(getegid());	

   [infoController setVersionValue: version];
   procType = BUILDING_MENU;
   subProc = [[Subprocess alloc] init: "uuname" withDelegate: self];
   [progress setIntValue: -1];
   [progress setStepSize: 10];
   return self;
}

- appWillTerminate:sender
{
   if(procType != NO_SPROC)
       [subProc free];

   if(auditProc)
       [auditProc free];

   if(logfile)
       [logfile free];

   if(syslog)
       [syslog free];

   return self;
}

@end					     /* ApplicationDelegate */


@implementation ConController (SubprocessDelegate)

- subprocess:sender done:(int)exitStatus
{
   switch(procType)
   {
    case BUILDING_MENU:
      [[hostsPopUp target] removeItem: [hostsPopUp title]];
      [hostsPopUp setTitle: [[[[hostsPopUp target] itemList] cellAt:0:0] title]];
					     /* choose the default host if one set */
      if([[hostsPopUp target] indexOfItem: [defaults get: "DefaultHost"]] != -1)
	  [hostsPopUp setTitle: [defaults get: "DefaultHost"]];

      [consoleLog appendString: "Ready to go.\n"];

      if(*[defaults get: "ShowLog"] == 'Y')
	  [self logfile: self];

      if(*[defaults get: "ShowSysLog"] == 'Y')
	  [self syslog: self];

      [window makeKeyAndOrderFront: self];

      break;

    case HOST_QUEUE:
      [consoleLog appendString: "\nQueue Complete\n"];
      break;

    case SNAP_HOSTS:
      [consoleLog appendString: "\nSnapshot Complete\n"];
      break;

    case POLL_HOST:

      if(auditProc)
      {
	 [consoleLog appendString:"\nDebug Poll done.\n"];
	 [NXApp delayedFree: auditProc];
	 auditProc = nil;
	 unlink(auditFile);
      }
      
      break;

    case DELETE_JOB:
      [consoleLog appendString: "\nDelete Complete\n"];
      break;

    case GET_BPS:
      [consoleLog appendString: "\nSpeed Listing Complete.\n"];
      break;

    case NO_SPROC:
      return self;			     /* don't want to free unknown */
      break;
   }

   if(sender == subProc)
   {
      procType = NO_SPROC;
      [self _endSweep];
   }
   
   [NXApp delayedFree: sender];
   return self;
}

- subprocess:sender output:(char *)buffer
{

   [progress increment: self];

   switch(procType)
   {
    case BUILDING_MENU:
      [[hostsPopUp target] addItem: buffer];
      break;

    default:
      [consoleLog appendString: buffer];
      [consoleLog appendString: "\n"];
      break;
   }

   return self;
}

- subprocess:sender stderrOutput:(char *)buffer
{
   [progress increment: self];

   [consoleLog appendString: buffer];
   return self;
}

- subprocess:sender error:(const char *)errorString
{
   [consoleLog appendString: "Failed to create subprocess.\n"];
   return self;
}


@end


void sweepIncrement(DPSTimedEntry teNumber, double now, void *userData)
{
   [*(id *)userData increment: nil];
}
